Funções de uma variável real com valores vetoriais

Funções de uma variável real com valores vetoriais#

Vamos considerar funções do tipo

\[\begin{equation*} F : \mathbb{R} \to \mathbb{R}^2 \ \ \text{ ou } \ \ F : \mathbb{R} \to \mathbb{R}^3 \end{equation*}\]

às vezes podemos escrever a função com uma seta acima, da forma $\overrightarrow{F}$, para enfatizar que trata-se de uma função com valores vetoriais.

Hide code cell source
# HIDE CODE
import plotly.express as px
import plotly.graph_objects as go
import numpy as np

Hélice#

Vamos começar com a curva conhecida como Hélice, que pode ser parametriada por $\overrightarrow{F}(t) = \left(\cos(t), \text{sen}(t), t \right)$. Na figura abaixo podemos ver o traço com o parâmetro $t$ percorrendo o intervalo $0 \leqslant t \leqslant 6\pi$.

Hide code cell source
# HIDE CODE
pontos = 100
t = np.linspace(0, 6*np.pi, pontos, endpoint=True)
x=np.cos(t)
y=np.sin(t)
z=t

fig2 = px.line_3d(x=x, y=y, z=z)
fig = px.scatter_3d(x=x, y=y, z=z, animation_frame=t, size = 12*np.ones(pontos),labels={'animation_frame':'t'}) # animação dos pontos da hélice
fig.add_trace(fig2.data[0]) # adicionar a curva
fig.layout.updatemenus[0].buttons[0].args[1]['frame']['duration'] = 0 # duração da transição da animação

fig.show()

Ciclóide#

Vejamos agora o exemplo de uma curva famosa, chamada ciclóide. É a curva gerada a partir da trajetória de um ponto sobre a circunferência que “anda” sobre uma linha reta sem deslizar.

Hide code cell source
# HIDE CODE
#para mais detalhes de animação ver o exemplo mri https://plotly.com/python/visualizing-mri-volume-slices/

pontos = 100
teta = np.linspace(0, 4*np.pi, pontos, endpoint=True)
phi = np.linspace(0, 2*np.pi, pontos, endpoint=True)


x = teta - np.sin(teta)
y = 1 - np.cos(teta)
xmin = np.min(x)
xmax = np.max(x)
ymin = np.min(y)
ymax = np.max(y)

data = [go.Scatter(x=x,y= y,mode="lines", line=dict(color="red")), # Mostrar antes do início da animação
        go.Scatter(),go.Scatter()] # outros traços (vazios) que serão modificados em cada frame

frames = [go.Frame(data = go.Scatter(x=teta[p] + np.cos(phi),y= 1 + np.sin(phi), #Adiciona a circunferencia que gira
                                    showlegend=False, mode="lines", line=dict(color="blue")
                                    ),
          name=str(p)
                  )
          for p in range(pontos)
         ]

def frame_args(duration,transition): # tempo de duração e transição dos frames
    return {
            "frame": {"duration": duration},
            "mode": "immediate",
            "fromcurrent": True,
            "transition": {"duration": transition, "easing": "linear"},
        }


layout=go.Layout(
        xaxis=dict(range=[xmin-1.2,xmax + 1.2], autorange=False, zeroline=False),
        yaxis=dict(range=[ymin-0.5,ymax + 0.5], autorange=False, zeroline=False,
                  scaleanchor = "x",scaleratio = 1,), # gráfico em escala 1:1
        title_text="Ciclóide", hovermode="closest",
        updatemenus=[dict(type="buttons",
                          buttons=[dict(label= "▶", # play symbol,
                                        method="animate",
                                        args=[None,frame_args(0,0)])])])

for k in range(len(frames)): # Adiciona o ponto sobre a circunferência e traço deixado ao girar (cicloide)
    tetap = np.linspace(0, teta[k], pontos, endpoint=True)
    frames[k].data = frames[k].data + (go.Scatter(x = tetap - np.sin(tetap),y = 1 - np.cos(tetap),
                                      showlegend=False,
                                      marker=dict(color="red")
                                                 )
                                      ,)
    frames[k].data = frames[k].data + (go.Scatter(x = [tetap[-1] - np.sin(tetap[-1])],y = [1 - np.cos(tetap[-1])],
                                        showlegend=False,
                                        mode="markers",
                                        marker=dict(color="red", size=10)
                                                )                                   
                                      ,)

figura = go.Figure(data = data, layout = layout, frames = frames)

figura.show()    

A ciclóide pode ser parametrizada por $\overrightarrow{F}(\theta) = \left( \theta - \text{sen}(\theta), 1 - \cos(\theta) \right)$, vejamos abaixo o gráfico com o parâmetro $\theta$ no intervalo $[0, 4\pi]$.

Hide code cell source
# HIDE CODE
pontos = 100
teta = np.linspace(0, 4*np.pi, pontos, endpoint=True)

x = teta - np.sin(teta)
y = 1 - np.cos(teta)
xmin = np.min(x)
xmax = np.max(x)
ymin = np.min(y)
ymax = np.max(y)

fig = px.scatter(x=x, y=y, animation_frame=teta, labels={'animation_frame' : 'θ'})
fig.update_traces(marker=dict(size=12))
fig2 = px.line(x=x, y=y)
fig.add_trace(fig2.data[0])

fig.update_yaxes(scaleanchor = "x",scaleratio = 1,)
fig.update_xaxes(range=[xmin-0.5,xmax + 0.5])
fig.update_yaxes(range=[ymin-0.5,ymax + 0.5])

fig.layout.updatemenus[0].buttons[0].args[1]['frame']['duration'] = 40 # intervalo entre frames em ms, para controlar a duração da animação    

fig.show()

Curva plana parametrizada#

Hide code cell source
# HIDE CODE
pontos = 100
t = np.linspace(-1, 1, pontos)
x = t + t ** 2
y = t - t ** 2
s = np.linspace(-1, 1, pontos)
xx = (1 + 2*s)#/np.sqrt(2+4*s**2)
yy = (1 - 2*s)#/np.sqrt(2+4*s**2)
xm = np.min(np.concatenate((x,x+xx))) - 0.5
xM = np.max(np.concatenate((x,x+xx))) + 0.5
ym = np.min(np.concatenate((y,y+yy))) - 0.5
yM = np.max(np.concatenate((y,y+yy))) + 0.5


# Create figure
fig = go.Figure(
    data=[go.Scatter(name = "",x=x, y=y,
                     mode="lines",
                     line=dict(width=2, color="blue")),
          go.Scatter(name = "Curva",x=x, y=y,
                     mode="lines",
                     line=dict(width=2, color="blue"))],
    layout=go.Layout(
        xaxis=dict(range=[xm, xM], autorange=False, zeroline=False),
        yaxis=dict(range=[ym, yM], autorange=False, zeroline=False),
        title_text="Curva plana parametrizada", hovermode="closest",
        updatemenus=[dict(type="buttons",
                          buttons=[dict(label="Play",
                                        method="animate",
                                        args=[None,{
            "frame": {"duration": 20}}])])]),
    frames=[go.Frame(
        data=[go.Scatter(name = "Vetor tangente",
            x=[x[k], x[k] + xx[k]],
            y=[y[k], y[k] + yy[k]],
            mode="lines+markers",
            line=dict(color='red'),
            marker=dict(color="red", size=20,symbol= "arrow",angleref="previous"))])

        for k in range(pontos)]
)

fig.update_yaxes(scaleanchor = "x",scaleratio = 1,)
fig.show()

Circunferência#

Hide code cell source
# HIDE CODE
pontos = 300
t = np.linspace(0, 3*np.pi, pontos)
x = np.cos(t)
y = np.sin(t)
s = np.linspace(-1, 1, pontos)
xx = -np.sin(t)
yy = np.cos(t)
xm = np.min(np.concatenate((x,x+xx))) - 0.5
xM = np.max(np.concatenate((x,x+xx))) + 0.5
ym = np.min(np.concatenate((y,y+yy))) - 0.5
yM = np.max(np.concatenate((y,y+yy))) + 0.5


# Create figure
fig = go.Figure(
    data=[go.Scatter(name = "",x=x, y=y,
                     mode="lines",
                     line=dict(width=2, color="blue")),
          go.Scatter(name = "Curva",x=x, y=y,
                     mode="lines",
                     line=dict(width=2, color="blue"))],
    layout=go.Layout(
        xaxis=dict(range=[xm, xM], autorange=False, zeroline=False),
        yaxis=dict(range=[ym, yM], autorange=False, zeroline=False),
        title_text="Circunferência", hovermode="closest",
        updatemenus=[dict(type="buttons",
                          buttons=[dict(label="Play",
                                        method="animate",
                                        args=[None,{
            "frame": {"duration": 20}}])])]),
    frames=[go.Frame(
        data=[go.Scatter(name = "Vetor tangente",
            x=[x[k], x[k] + xx[k]],
            y=[y[k], y[k] + yy[k]],
            mode="lines+markers",
            line=dict(color='red'),
            marker=dict(color="red", size=20,symbol= "arrow",angleref="previous"))])

        for k in range(pontos)]
)

fig.update_yaxes(scaleanchor = "x",scaleratio = 1,)
fig.show()

Hélice e seus vetores tangentes#

Hide code cell source
# HIDE CODE
pontos = 300
t = np.linspace(0, 3*np.pi, pontos)
x = np.cos(t)
y = np.sin(t)
z = t
s = np.linspace(-1, 1, pontos)
u = -np.sin(t)
v = np.cos(t)
w = np.ones(pontos)
xm = np.min(np.concatenate((x,x+u))) - 4
xM = np.max(np.concatenate((x,x+u))) + 4
ym = np.min(np.concatenate((y,y+v))) - 4
yM = np.max(np.concatenate((y,y+v))) + 4
zm = np.min(np.concatenate((z,z+w))) - 4
zM = np.max(np.concatenate((z,z+w))) + 4


# Create figure
fig = go.Figure(
    data=[go.Scatter3d(name = "",x=x, y=y,z=z,
                     mode="lines",
                     line=dict(width=2, color="blue")),
          go.Scatter3d(),
          go.Scatter3d(name = "Curva",x=x, y=y,z=z,
                     mode="lines",
                     line=dict(width=2, color="blue"))
        ],
    layout=go.Layout(
        title_text="Hélice e seus vetores tangentes", hovermode="closest",
        updatemenus=#[dict(type="buttons",
                    #      buttons=[dict(label="Play",
                    #                    method="animate",
                    #                    args=[None,{
                    #"frame": {"duration": 20}}])])]
                    [
            {
                "buttons": [
                    {
                        "args": [None, {"frame": {"duration": 20},
                                          "mode": "immediate",
                                          "fromcurrent": True,
                                          "transition": {"duration": 20, "easing": "linear"}}],
                        "label": "▶", # play symbol
                        "method": "animate",
                    },
                    {
                        "args": [[None], {"frame": {"duration": 0},
                                          "mode": "immediate",
                                          "fromcurrent": True,
                                          "transition": {"duration": 0, "easing": "linear"}}],
                        "label": "◼", # pause symbol
                        "method": "animate",
                    },
                ],
                "direction": "left",
                "pad": {"r": 10, "t": 70},
                "type": "buttons",
                "x": 0.1,
                "y": 0,
            }
         ]
                    ),
    frames=[go.Frame(
        data=[
            go.Cone(name = "Vetor tangente",
            x = [x[k] + u[k]],
            y = [y[k] + v[k]],
            z = [z[k] + w[k]],
            u = [u[k]],
            v = [v[k]],
            w = [w[k]],
            #mode="lines+markers",
            colorscale=[[1, 'red'], [1, 'red']],
            showscale=False,
            #marker=dict(color="red", size=20,
            #            symbol= "square",
            #angleref="previous"
            #            )
                        ),
            go.Scatter3d(name = "Vetor tangente",
                         x = [x[k], x[k] + u[k]],
                         y = [y[k], y[k] + v[k]],
                         z = [z[k], z[k]+ w[k]],
                         mode = "lines",
                         line=dict(width=2, color="red")
                         )
            ])

        for k in range(pontos)]
)

fig.update_layout(scene = dict(
        xaxis = dict(nticks=4, range=[-2,2],),
                     yaxis = dict(nticks=4, range=[-2,2],),
                     zaxis = dict(nticks=4, range=[0,12],),),)
fig.show()
Hide code cell source
# HIDE CODE
pontos = 360
t = np.linspace(0, 3*np.pi, pontos)
x = np.cos(t)
y = np.sin(t)
z = t
s = np.linspace(-1, 1, pontos)
u = -np.sin(t)
v = np.cos(t)
w = np.ones(pontos)

data=[]
for k in range(0,360,60):
    data.append(
        go.Cone(name = "Vetor tangente",
            x = [x[k] + u[k]],
            y = [y[k] + v[k]],
            z = [z[k] + w[k]],
            u = [u[k]],
            v = [v[k]],
            w = [w[k]],
            colorscale=[[1, 'red'], [1, 'red']],
            showscale=False,
                        )
                )
    data.append(
        go.Scatter3d(name = "Vetor tangente",
                         x = [x[k], x[k] + u[k]],
                         y = [y[k], y[k] + v[k]],
                         z = [z[k], z[k]+ w[k]],
                         mode = "lines",
                         line=dict(width=2, color="red")
                         )
                )
data.append(go.Scatter3d(name = "",x=x, y=y,z=z,
                     mode="lines",
                     line=dict(width=2, color="blue")))
fiig=go.Figure(data=data)

fiig.update_layout(showlegend=False)

fiig.show()